import torch
import torch.optim as optim
import torch.nn.functional as F
# import VGG16

class InceptionA(torch.nn.Module):
    def __init__(self,in_channels):
        super(InceptionA, self).__init__()
        # 分支 1
        self.branch_1_1x1 =torch.nn.Conv2d(in_channels=in_channels,
                                         out_channels=24,
                                         kernel_size=1,
                                         stride=1)
        self.ave_pool = torch.nn.AvgPool2d(kernel_size=3,
                                           padding=1,
                                           stride=1)
        # 分支 2
        self.branch_2_1x1 = torch.nn.Conv2d(in_channels=in_channels,
                                            out_channels=16,
                                            kernel_size=1,
                                            stride=1)
        # 分支 3
        self.branch_3_1x1 = torch.nn.Conv2d(in_channels=in_channels,
                                            out_channels=16,
                                            kernel_size=1,
                                            stride=1)
        self.branch_3_5x5 = torch.nn.Conv2d(in_channels=16,
                                            out_channels=24,
                                            kernel_size=5,
                                            padding=2,
                                            stride=1)
        # 分支 4
        self.branch_4_1x1 = torch.nn.Conv2d(in_channels=in_channels,
                                            out_channels=16,
                                            kernel_size=1,
                                            stride=1)
        self.branch_4_3x3_1 = torch.nn.Conv2d(in_channels=16,
                                            out_channels=24,
                                            kernel_size=3,
                                            padding=1,
                                            stride=1)
        self.branch_4_3x3_2 = torch.nn.Conv2d(in_channels=24,
                                            out_channels=24,
                                            kernel_size=3,
                                            padding=1,
                                            stride=1)

    def forward(self,x):
        branch_1 = self.branch_1_1x1(self.ave_pool(x))
        branch_2 = self.branch_2_1x1(x)
        branch_3 = self.branch_3_5x5(self.branch_3_1x1(x))
        branch_4 = self.branch_4_3x3_2(self.branch_4_3x3_1(self.branch_4_1x1(x)))
        outputs = [branch_1,branch_2,branch_3,branch_4]

        return torch.cat(outputs,dim=1) # 按照通道进行连接  b(batch),c(channel),w(width),h(height)

class Net(torch.nn.Module):
    def __init__(self,num_classes):
        super(Net, self).__init__()
        self.conv1 =torch.nn.Conv2d(1,10,kernel_size=5)
        self.conv2 = torch.nn.Conv2d(88,20,kernel_size=5) # 88 = 24*3+16
        self.incep1 = InceptionA(in_channels=10)
        self.incep2 = InceptionA(in_channels=20)
        self.mp = torch.nn.MaxPool2d(2)
        self.fc = torch.nn.Linear(1408,num_classes)

    def forward(self,x):
        in_size = x.size(0) # 得到样品个数
        x = F.relu(self.mp(self.conv1(x)))
        x = self.incep1(x)
        x = F.relu(self.mp(self.conv2(x)))
        x = self.incep2(x)
        x = x.view(in_size,-1) # 化为二维(这里两个参数对应行和列)
        x = self.fc(x)
        return x
